<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
    xmlns:zfiml ="http://ZF-IML.org"
	xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
	xmlns:xs="http://www.w3.org/2001/XMLSchema" 
	xmlns:aorml="http://AOR-AppML.org">
	<xsl:output method="xml" />
	<xsl:output name="xml" method="xml" />
	<xsl:variable name="break"><xsl:text>
</xsl:text></xsl:variable>
    <xsl:variable name="tab"><xsl:text>    </xsl:text></xsl:variable>
    <!--path for helium: /srv/www/webapps/oryx/test/ -->
    <!-- path on local windows: file:///Program Files/apache-tomcat6/webapps/oryx/test/ -->
    <xsl:variable name="filepath"><xsl:text></xsl:text></xsl:variable>
    <xsl:function name="aorml:upperFirst" as="xs:string?">
        <xsl:param name="trans" as="xs:string?"></xsl:param>
        <xsl:sequence select="concat(upper-case(substring($trans,1,1)),substring($trans,2))"/>
    </xsl:function>
    <xsl:function name="aorml:lowerFirst" as="xs:string?">
        <xsl:param name="trans" as="xs:string?"></xsl:param>
        <xsl:sequence select="concat(lower-case(substring($trans,1,1)),substring($trans,2))"/>
    </xsl:function>
    
	<xsl:template match="/">
	   <xsl:result-document href="{$filepath}ZF-IML.xml" format="xml">
	       <xsl:value-of select="$break" />
            <zfiml:ZFApplication xmlns:zfiml ="http://ZF-IML.org" 
                    xmlns:p="http://purl.org/dc/elements/1.1/" 
                    xmlns:xml="http://www.w3.org/XML/1998/namespace" 
                    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
                    xsi:schemaLocation="http://ZF-IML.org ZF-IML.xsd">
                    <xsl:call-template name="getObjectTypes" />
                <xsl:call-template name="getM2MAssociations" />
            <xsl:value-of select="$break" />
            </zfiml:ZFApplication>
        </xsl:result-document>
	</xsl:template>
	
    <xsl:template name="getObjectTypes">
        <xsl:for-each select="/aorml:Application/aorml:ObjectType">
            <xsl:value-of select="concat($break,$tab)" />
            <xsl:element name="zfiml:ObjectType">
                <xsl:attribute name="name">
                    <xsl:value-of select="@name" />
                </xsl:attribute>
                <xsl:variable name="objectTypeName" select="@name"/>
                <xsl:if test="@superType">
                    <xsl:attribute name="superType">
                        <xsl:value-of select="@superType" />
                    </xsl:attribute>
                </xsl:if>
                <!-- get Attributes -->            
                <xsl:for-each select="aorml:Attribute[not(@upperMultiplicity)
                    or(@upperMultiplicity='1')]
                    | aorml:EnumerationProperty">
                    <xsl:value-of select="concat($break,$tab,$tab)" />
                    <xsl:if test="name()='aorml:Attribute'">
                        <xsl:element name="zfiml:Attribute">
                            <xsl:attribute name="name">
                                <xsl:value-of select="@name" />
                            </xsl:attribute>
                            <xsl:attribute name="type">
                                <xsl:value-of select="@type" />
                            </xsl:attribute>
                            <xsl:if test="@upperMultiplicity">
                                <xsl:attribute name="upperMultiplicity">
                                    <xsl:value-of select="@upperMultiplicity" />
                                </xsl:attribute>
                            </xsl:if>
                            <xsl:if test="@lowerMultiplicity">
                                <xsl:attribute name="lowerMultiplicity">
                                    <xsl:value-of select="@lowerMultiplicity" />
                                </xsl:attribute>
                            </xsl:if>
                            <xsl:if test="@isStatic">
                                <xsl:attribute name="isStatic">
                                    <xsl:value-of select="@isStatic" />
                                </xsl:attribute>
                            </xsl:if>
                            <xsl:if test="@initialValue">
                                <xsl:attribute name="initialValue">
                                    <xsl:value-of select="@initialValue" />
                                </xsl:attribute>
                            </xsl:if>
                            <xsl:if test="@minValue">
                                <xsl:attribute name="minValue">
                                    <xsl:value-of select="@minValue" />
                                </xsl:attribute>
                            </xsl:if>
                            <xsl:if test="@maxValue">
                                <xsl:attribute name="maxValue">
                                    <xsl:value-of select="@maxValue" />
                                </xsl:attribute>
                            </xsl:if>
                            <xsl:if test="@isStandardID">
                                <xsl:attribute name="isStandardID">
                                    <xsl:value-of select="@isStandardID" />
                                </xsl:attribute>
                            </xsl:if>
                            <xsl:if test="@isInfo">
                                <xsl:attribute name="isInfo">
                                    <xsl:value-of select="@isInfo" />
                                </xsl:attribute>
                            </xsl:if>
                            <xsl:if test="@label">
                                <xsl:attribute name="label">
                                    <xsl:value-of select="@label" />
                                </xsl:attribute>
                            </xsl:if>
                        </xsl:element>
                    </xsl:if>
                    <xsl:if test="name()='aorml:EnumerationProperty'">
                        <xsl:element name="zfiml:EnumerationProperty">
                            <xsl:attribute name="name" select="@name" />
                            <xsl:attribute name="type" select="@name" />
                            <xsl:if test="@upperMultiplicity">
                                <xsl:attribute name="upperMultiplicity">
                                    <xsl:value-of select="@upperMultiplicity" />
                                </xsl:attribute>
                            </xsl:if>
                            <xsl:if test="@lowerMultiplicity">
                                <xsl:attribute name="lowerMultiplicity">
                                    <xsl:value-of select="@lowerMultiplicity" />
                                </xsl:attribute>
                            </xsl:if>
                            <xsl:if test="@isStatic">
                                <xsl:attribute name="isStatic">
                                    <xsl:value-of select="@isStatic" />
                                </xsl:attribute>
                            </xsl:if>
                            <xsl:if test="@initialValue">
                                <xsl:attribute name="initialValue">
                                    <xsl:value-of select="@initialValue" />
                                </xsl:attribute>
                            </xsl:if>
                            <xsl:variable name="enumName">
                                <xsl:value-of select="@type"></xsl:value-of>
                            </xsl:variable>
                            <xsl:if test="@label">
                                <xsl:attribute name="label">
                                    <xsl:value-of select="@label" />
                                </xsl:attribute>
                            </xsl:if>
                            <xsl:for-each select="/aorml:Application/aorml:Enumeration
                                [@name=$enumName]/aorml:EnumerationLiteral">
                                <xsl:value-of select="concat($break,$tab,$tab,$tab)" />
                                <xsl:element name="zfiml:EnumerationLiteral">
                                    <xsl:attribute name="value">
                                        <xsl:value-of select="."></xsl:value-of>
                                    </xsl:attribute>
                                </xsl:element>
                            </xsl:for-each>
                            <xsl:value-of select="concat($break,$tab,$tab)" />
                        </xsl:element>
                     </xsl:if>
                </xsl:for-each>
               
                
            <!-- get ReferenceProperties  -->
            
                <!-- ZF-ReferenceProperty  
                    where this ObjectTable is domain-->
                <xsl:for-each select="//aorml:BiNavigableAssociation[@domain=$objectTypeName]
                                    |//aorml:NavigableAssociation[@domain=$objectTypeName]">
                    <xsl:value-of select="concat($break,$tab,$tab)" />
                    <xsl:element name="zfiml:ZF-ReferenceProperty">
                        <xsl:attribute name="type" select="@range" />                        
                        <xsl:attribute name="name">
                            <xsl:value-of select="aorml:lowerFirst(@rangeRoleName)" />
                            <xsl:if test="not(@rangeRoleName)">
                                <xsl:value-of select="aorml:lowerFirst(@range)"></xsl:value-of>
                            </xsl:if>
                        </xsl:attribute>
                        <xsl:if test="@domainRoleName">
                            <xsl:attribute name="inverseRoleName">
                                <xsl:value-of select="aorml:lowerFirst(@domainRoleName)"></xsl:value-of>
                            </xsl:attribute>
                        </xsl:if>
                        <!-- if ManyToMany-Association -->
                        <xsl:if test="(@rangeMultiplicity='*' or @rangeMultiplicity='1..*')and
                                    (@domainMultiplicity='*' or @domainMultiplicity='1..*')">
                            <xsl:attribute name="viaManyToManyAssociation">
                                <xsl:value-of select="@name"></xsl:value-of>
                                <xsl:if test="not(@name)">
                                    <xsl:value-of select="@domain"></xsl:value-of>
                                    <xsl:value-of select="aorml:lowerFirst(@range)"></xsl:value-of>
                                </xsl:if>
                            </xsl:attribute>
                        </xsl:if>
                        <xsl:call-template name="transMultiplicity">
                            <xsl:with-param name="multiplicity" select="@rangeMultiplicity" />
                        </xsl:call-template>
                    </xsl:element>
                </xsl:for-each>
                
                <!--  ZF-ReferenceProperty  
                    where this ObjectTable is range-->
                <xsl:for-each select="//aorml:BiNavigableAssociation[@range=$objectTypeName]
                                    |//aorml:NavigableAssociation[@range=$objectTypeName]">
                    <xsl:value-of select="concat($break,$tab,$tab)" />
                    <xsl:element name="zfiml:ZF-ReferenceProperty">
                        <xsl:attribute name="type" select="@domain" />
                        <xsl:attribute name="name">
                            <xsl:value-of select="aorml:lowerFirst(@domainRoleName)" />
                            <xsl:if test="not(@domainRoleName)">
                                <xsl:value-of select="aorml:lowerFirst(@domain)"></xsl:value-of>
                            </xsl:if>
                        </xsl:attribute>
                        <xsl:if test="@rangeRoleName">
                            <xsl:attribute name="inverseRoleName">
                                <xsl:value-of select="aorml:lowerFirst(@rangeRoleName)"></xsl:value-of>
                            </xsl:attribute>
                        </xsl:if>
                        <xsl:if test="(@rangeMultiplicity='*' or @rangeMultiplicity='1..*')and
                                    (@domainMultiplicity='*' or @domainMultiplicity='1..*')">
                            <xsl:attribute name="viaManyToManyAssociation">
                                <xsl:value-of select="@name"></xsl:value-of>
                                <xsl:if test="not(@name)">
                                    <xsl:value-of select="@domain"></xsl:value-of>
                                    <xsl:value-of select="aorml:lowerFirst(@range)"></xsl:value-of>
                                </xsl:if>
                            </xsl:attribute>
                        </xsl:if>
                        <xsl:call-template name="transMultiplicity">
                            <xsl:with-param name="multiplicity" select="@domainMultiplicity" />
                        </xsl:call-template>
                        <!-- functional and inverse functional association range end signed as derived -->
                        <xsl:if test="(@rangeMultiplicity='1' or @rangeMultiplicity='0..1')and
                                    (@domainMultiplicity='1' or @domainMultiplicity='0..1')">
                            <xsl:attribute name="derived" select="'true'"></xsl:attribute>
                        </xsl:if>
                        
                    </xsl:element>
                </xsl:for-each>
                <xsl:value-of select="concat($break,$tab)" />
            </xsl:element>
        </xsl:for-each>
    </xsl:template>
    
    <!-- get Associations from Many to Many Associations -->
    <xsl:template name="getM2MAssociations">
        <xsl:for-each select="//aorml:BiNavigableAssociation[
                (@rangeMultiplicity='*' or @rangeMultiplicity='1..*')and
                (@domainMultiplicity='*' or @domainMultiplicity='1..*')]
                |//aorml:NavigableAssociation[(@rangeMultiplicity='*' 
                or @rangeMultiplicity='1..*')and
                (@domainMultiplicity='*' or @domainMultiplicity='1..*')]">
            <xsl:variable name="domain">
                <xsl:value-of select="@domain"></xsl:value-of>
            </xsl:variable>
            <xsl:variable name="range">
                <xsl:value-of select="@range"></xsl:value-of>
            </xsl:variable>
            <xsl:value-of select="concat($break,$tab)" />
            <xsl:element name="zfiml:ManyToManyAssociation">
                <xsl:attribute name="name">
                    <xsl:value-of select="@name" />
                    <xsl:if test="not(@name)">
                        <xsl:value-of select="@domain"></xsl:value-of>
                        <xsl:value-of select="aorml:lowerFirst(@range)"></xsl:value-of>
                    </xsl:if>
                </xsl:attribute>
                <!-- ReferenceProperty of Domain -->
                <xsl:value-of select="concat($break,$tab,$tab)" />
                <xsl:element name="zfiml:ZF-ReferenceProperty">
                    <xsl:attribute name="name">
                        <xsl:value-of select="@domainRoleName"></xsl:value-of>
                        <xsl:if test="not(@domainRoleName)">
                            <xsl:value-of select="aorml:lowerFirst(@domain)"></xsl:value-of>
                        </xsl:if>
                    </xsl:attribute>
                    <xsl:attribute name="type">
                        <xsl:value-of select="@domain"></xsl:value-of>
                    </xsl:attribute>
                    <xsl:attribute name="upperMultiplicity" select="'unbounded'" />
                </xsl:element>
                <!-- ReferenceProperty of Range -->
                <xsl:value-of select="concat($break,$tab,$tab)" />
                <xsl:element name="zfiml:ZF-ReferenceProperty">
                    <xsl:attribute name="name">
                        <xsl:value-of select="@rangeRoleName"></xsl:value-of>
                        <xsl:if test="not(@rangeRoleName)">
                            <xsl:value-of select="aorml:lowerFirst(@range)"></xsl:value-of>
                        </xsl:if>
                    </xsl:attribute>
                    <xsl:attribute name="type">
                        <xsl:value-of select="@range"></xsl:value-of>
                    </xsl:attribute>
                    <xsl:attribute name="upperMultiplicity" select="'unbounded'" />
                </xsl:element>
                <xsl:value-of select="concat($break,$tab)" />
            </xsl:element>            
        </xsl:for-each>
    </xsl:template>
	
    <!-- translate association-multiplicity to lower-upper attributes -->
    <xsl:template name="transMultiplicity" >
        <xsl:param name="multiplicity"></xsl:param>
        <xsl:if test="$multiplicity='0..1'">
            <xsl:attribute name="lowerMultiplicity" select="0" />
        </xsl:if>
        <xsl:if test="$multiplicity='1..*'">
            <xsl:attribute name="upperMultiplicity" select="'unbounded'" />
        </xsl:if>
        <xsl:if test="$multiplicity='*'">
            <xsl:attribute name="lowerMultiplicity" select="0" />
            <xsl:attribute name="upperMultiplicity" select="'unbounded'" />
        </xsl:if>
    </xsl:template>
    
</xsl:stylesheet>